using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Ink;
using System.Windows;
using System.Xml.Serialization;
using WozLib.UI.Ink.SketchObjects;
using WozLib.UI.Ink.SketchElements;
using System.Windows.Controls;

namespace WozLib.UI.Ink.SketchCommands
{
  public class ReplacementSketchCommand : SketchCommand
  {

    [XmlElement("ChangeSelectionSketchCommand")]
    public ChangeSelectionSketchCommand ChangeSelectionSketchCommand
    {
      get { return _ChangeSelectionSketchCommand; }
      set { _ChangeSelectionSketchCommand = value; }
    } private ChangeSelectionSketchCommand _ChangeSelectionSketchCommand;

    [XmlElement("CreateSketchCommand")]
    public CreateSketchCommand CreateSketchCommand
    {
      get { return _CreateSketchCommand; }
      set { _CreateSketchCommand = value; }
    } private CreateSketchCommand _CreateSketchCommand;

    [XmlElement("EraseSketchCommand")]
    public EraseSketchCommand EraseSketchCommand
    {
      get { return _EraseSketchCommand; }
      set { _EraseSketchCommand = value; }
    } private EraseSketchCommand _EraseSketchCommand;

    public ReplacementSketchCommand()
    {
    }

    public ReplacementSketchCommand(SketchPad sourcePad, SketchPad destination, IEnumerable<SketchObject> toReplace)
      : base()
    {
      // the main trick here is our source objects (all the objects in the source pad)
      // are in a different object registry and need to be cloned and put into our registry
      // we use destination's registry for this purpose
      List<SketchObject> toAdd = new List<SketchObject>();

      SketchPad sketchPad = sourcePad.Clone(toReplace,destination);

      // make the new sketch objects
      foreach (UIElement uie in sketchPad.Children)
      {
        if (uie is ISketchObject)
        {
          ISketchObject iSketchObject = uie as ISketchObject;

          ISketchObject newISketchObject = iSketchObject.GetWozObject().GetNewIWozObject(destination.WozObjectRegistry);
          toAdd.Add(newISketchObject.GetWozObject());
        }
      }
      foreach (Stroke stroke in sketchPad.Strokes)
      {
        if (stroke is ISketchObject)
        {
          ISketchObject iSketchObject = stroke as ISketchObject;

          ISketchObject newISketchObject = iSketchObject.GetWozObject().GetNewIWozObject(destination.WozObjectRegistry);
          toAdd.Add(newISketchObject.GetWozObject());
        }
      }

      // create the commands
      EraseSketchCommand = new EraseSketchCommand(toReplace);
      CreateSketchCommand = new CreateSketchCommand(toAdd);
      ChangeSelectionSketchCommand = new ChangeSelectionSketchCommand(toAdd, toReplace);
    }

    public override void Redo()
    {
      if (this.WozClientCommandReferences != null && this.WozClientCommandReferences.InkCanvas != null &&
        ChangeSelectionSketchCommand != null && CreateSketchCommand != null && EraseSketchCommand != null)
      {
        ChangeSelectionSketchCommand.WozClientCommandReferences = WozClientCommandReferences;
        CreateSketchCommand.WozClientCommandReferences = WozClientCommandReferences;
        EraseSketchCommand.WozClientCommandReferences = WozClientCommandReferences;

        EraseSketchCommand.Redo();
        CreateSketchCommand.Redo();

        // TOTAL HACK
        // this is because we don't have a general way to do event subscription of
        // new sketchobjects - turns out TextBoxes and Buttons are the only important
        // ones
        if (this.WozClientCommandReferences.InkCanvas is SketchPad)
        {
          foreach (SketchObject sketchObject in CreateSketchCommand.TargetWozObjects)
          {
            ISketchObject iSketchObject = sketchObject.GetIWozObject(this.WozClientCommandReferences.WozObjectRegistry);
            if (iSketchObject is SketchText)
            {
              (iSketchObject as SketchText).TextChanged += new TextChangedEventHandler(
                (this.WozClientCommandReferences.InkCanvas as SketchPad).wozText_TextChanged);
            }
          }
        }

        ChangeSelectionSketchCommand.Redo();
        SketchPad.CurrentInkTool = SketchPad.InkTools.Selector;
      }
    }

    public override void Undo()
    {
      if (this.WozClientCommandReferences != null && this.WozClientCommandReferences.InkCanvas != null &&
        ChangeSelectionSketchCommand != null && CreateSketchCommand != null && EraseSketchCommand != null)
      {
        ChangeSelectionSketchCommand.WozClientCommandReferences = WozClientCommandReferences;
        CreateSketchCommand.WozClientCommandReferences = WozClientCommandReferences;
        EraseSketchCommand.WozClientCommandReferences = WozClientCommandReferences;

        CreateSketchCommand.Undo();
        EraseSketchCommand.Undo();

        // we do this last because we play a little trick and set the things to be deleted
        // as the previous selected objects
        ChangeSelectionSketchCommand.Undo();
        SketchPad.CurrentInkTool = SketchPad.InkTools.Selector;
      }
    }

  }
}
